package cn.itsource.pethome.system.logininfo.service.impl;

import cn.itsource.pethome.base.service.impl.IBaseServiceImpl;
import cn.itsource.pethome.jwt.PayloadData;
import cn.itsource.pethome.system.logininfo.domain.LoginRO;
import cn.itsource.pethome.system.logininfo.domain.LoginVO;
import cn.itsource.pethome.system.logininfo.domain.Logininfo;
import cn.itsource.pethome.system.logininfo.mapper.LogininfoMapper;
import cn.itsource.pethome.system.logininfo.service.ILogininfoService;


import cn.itsource.pethome.system.menu.domain.Menu;
import cn.itsource.pethome.system.menu.service.IMenuService;
import cn.itsource.pethome.system.role.mapper.RoleMapper;
import cn.itsource.pethome.system.user.domain.Employee;
import cn.itsource.pethome.system.user.domain.User;
import cn.itsource.pethome.system.user.mapper.UserMapper;
import cn.itsource.pethome.system.user.service.IEmployeeService;
import cn.itsource.pethome.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zcj
 * @since 2023-01-11
 */
@Service
public class LogininfoServiceImpl extends IBaseServiceImpl<Logininfo> implements ILogininfoService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IEmployeeService employeeService;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private IMenuService iMenuService;
    @Autowired
    private UserMapper userMapper;
    @Value("${jwt.rsa.pri}")
    private String pri;

    @Override
    public AjaxResult account(LoginRO login) {
        if(login.getType() == null){
            throw new BusinessException("非法访问");
        }
        if(login.getPassword() == null || "".equals(login.getPassword().trim())){
            throw new BusinessException("密码不能为空");
        }
        if(login.getUsername() == null || "".equals(login.getUsername().trim())){
            throw new BusinessException("密码不能为空");
        }
        Logininfo account = logininfoMapper.account(login);
        if(account==null){
            throw new BusinessException("用户名或者密码错误");
        }
        if(login.getAutoLogin()){
            String password = login.getPassword();
            String salt = account.getSalt();//加密盐值
            String s = MD5Utils.encrypByMd5(password + salt);
            if(!account.getPassword().equals(s)){
                throw new BusinessException("用户名或者密码错误");
            }
        }
       return getJWTToken(account);
    }
    private AjaxResult getRedisToken(Logininfo account) {
        // 128位的随机数
        String token = StrUtils.getComplexRandomString(128);
        redisTemplate.opsForValue().set(token, account,30, TimeUnit.MINUTES);

        Long empId = employeeService.findByLogininfoId(account.getId()).getId();//根据Logininfoid查询员工id
        List<Long> roles = employeeService.findRoleByEmpId(empId);//获取到自己的角色
        List<String> permissionsByRoleIds = roleMapper.getPermissionsByRoleIds(roles);//自己有的权限
        redisTemplate.opsForValue().set(token+"permission",permissionsByRoleIds,30, TimeUnit.MINUTES);

        LoginVO loginVO = new LoginVO();
        loginVO.setToken(token);
        loginVO.setLogininfo(account);
        return AjaxResult.success().setData(loginVO).setMsg("managerLogin");
    }

    private AjaxResult getJWTToken(Logininfo account){
        LoginVO loginVO = new LoginVO();
        try {
            PayloadData payloadData = new PayloadData();
            if (account.getType() == 0){
                //获取empyyel的id
                Employee employee = employeeService.findByLogininfoId(account.getId());

                payloadData.setAdmin(employee);


                Long empId = employeeService.findByLogininfoId(account.getId()).getId();//根据Logininfoid查询员工id
                List<Long> roles = employeeService.findRoleByEmpId(empId);//获取到自己的角色
                List<String> permissionsByRoleIds = roleMapper.getPermissionsByRoleIds(roles);//自己有的权限
                //将权限设置到payloadData返回给前端
                payloadData.setPermissions(new HashSet<>(permissionsByRoleIds));
                //菜单比较特殊
                List<Menu> all = iMenuService.findAll();
                List<Long> menuByRole = iMenuService.findMenuByRole(roles);
                //构建自己菜单树
                ArrayList<Menu> c = new ArrayList<>();
                //自己找自己
                for (Menu menu : all) {
                    for (Long aLong : menuByRole) {
                        if (menu.getId().equals(aLong)){
                            c.add(menu);
                        }
                    }
                }
                /*找到父亲的id*/
                List<Long> parent = c.stream()
                        .map(Menu::getParentId)
                        .distinct()
                        .collect(Collectors.toList());

                ArrayList<Menu> p = new ArrayList<>();
                for (Menu menu : all) {
                    for (Long aLong : parent) {
                        if (menu.getId().equals(aLong)){
                            p.add(menu);
                        }
                    }
                }
                p.forEach(menu -> {
                    c.forEach(menu1 -> {
                        if (menu.getId()==menu1.getParentId()){
                            menu.getChildren().add(menu1);
                        }
                    });
                });

                payloadData.setMenus(p);
            }else {
           User user =  userMapper.findByLogininfoId(account.getId());
                payloadData.setUser(user);
            }

            //生成token
            PrivateKey privateKey = RsaUtils.getPrivateKey(JwtUtils.class.getClassLoader().getResource(pri).getFile());
            String token = JwtUtils.generateTokenExpireInMinutes(payloadData, privateKey, 30);
            System.out.println(token);
            loginVO.setEmployee(payloadData.getAdmin());
            loginVO.setLogininfo(account);
            loginVO.setMenus(payloadData.getMenus());
            loginVO.setToken(token);
            loginVO.setPermissions(payloadData.getPermissions());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success().setData(loginVO).setMsg("managerLogin");
    }
}
